Skip to main content

Process control

C programs are executed sequentially, i.e. the preceding statements are executed first and then the following ones. Developers who want to control the flow of program execution must use the syntactic constructs of flow control, mainly conditional and loop execution.

if statements

The if statement is used for conditional judgements, where the specified statement is executed when the condition is met.

if (expression) statement

In the above equation, the statement statement is executed when the expression expression is true (the value is not 0).

The judgment condition expression after if must be enclosed in parentheses, otherwise an error will be reported. The body part of the statement statement can be a statement or a compound statement inside curly brackets. Here is an example.

if (x == 10) printf("x is 10");

In the above example, a line of text is output when the variable x is 10. For statement bodies with only one statement, the statement part is usually on a separate line.

if (x == 10)
printf("x is 10\n");

If there are multiple statements, you need to put them inside curly brackets to form a compound statement.

if (line_num == MAX_LINES) {
line_num = 0;
page_num++;
}

The if statement can have an else branch, specifying the code to be executed if the condition does not hold (the value of the expression expression is 0).

if (expression) statement
else statement

Here is an example.

if (i > j)
max = i;
else
max = j;

If there are more than one line of else statements, again they can be placed inside curly brackets.

else can be used in conjunction with another `if statement to form multiple judgements.

if (expression)
statement
else if (expression)
statement
...
else if (expression)
statement
else
statement

If there is more than one if and else, you can remember the rule that else always matches the closest if.

if (number > 6)
if (number < 12)
printf("The number is more than 6, less than 12.\n");
else
printf("It is wrong number.\n");

In the example above, the else part matches the nearest if (i.e. number < 12), so if number is equal to 6, the else part is not executed.

This is error-prone, and to provide readability of the code it is recommended to use curly brackets to make it clear which else matches which if.

if (number > 6) {
if (number < 12) {
printf("The number is more than 6, less than 12.\n");
}
} else {
printf("It is wrong number.\n");
}

In the example above, the use of curly brackets makes it clear that else matches the outer if.

Ternary operators ?

C has a ternary expression ? :, which can be used as shorthand for if. .else in its shortened form.

<expression1> ? <expression2> : <expression3>

The meaning of this operator is that the expression expression1 is executed as expression2 if it is true (a non-zero value), otherwise it is executed as expression3.

Here is an example that returns the greater of two values.

(i > j) ? i : j;

The above code is equivalent to the following if statement.

if (i > j)
return i;
else
return j;

The switch statement

The switch statement is a special form of the if.... ...else construct, used when a condition has more than one result. It changes the multiple else ifs into an easier to use and more readable form.

switch (expression) {
case value1: statement
case value2: statement
default: statement
}

In the above code, the corresponding case branch is executed depending on the value of the expression expression. If the corresponding value is not found, then the default branch is executed.

Here is an example.

switch (grade) {
case 0:
printf("False");
break;
case 1:
printf("True");
break;
default:
printf("Illegal");
}

In the above example, different case branches are executed depending on the value of the variable grade. If it is equal to 0, the case 0 part is executed; if it is equal to 1, the case 1 part is executed; otherwise, the default part is executed. default means that all of the above cases are handled if they do not match.

At the end of each case statement body, there should be a break statement, which serves to jump out of the entire switch structure and not to proceed further. If break is missing, it will cause execution to continue to the next case or default branch.

switch (grade) {
case 0:
printf("False");
case 1:
printf("True");
break;
default:
printf("Illegal");
}

In the above example, there is no break statement in the case 0 section, so that when this branch is finished, it does not exit the switch structure and continue to execute the case 1 branch.

Using this feature, if multiple case branches correspond to the same statement body, you could write it like this.

switch (grade) {
case 0:
case 1:
printf("True");
break;
default:
printf("Illegal");
}

In the example above, the case 0 branch does not have any statements, resulting in the same body of statements being executed in both case 0 and case 1.

The body of the statement that follows case does not need to be inside curly braces, which is why break is needed.

The default branch is used to handle cases where none of the preceding cases match, and is best placed after all cases so that you don't have to write a break statement. This branch is optional; without it, if all the cases do not match, the entire switch block will be jumped.

while statement

The while statement is used in a loop structure to keep executing the loop body when the condition is met.

while (expression)
statement

In the above code, if the expression expression is a non-zero value (indicating true), the statement statement is executed and then again determines if expression is zero; if expression is zero (indicating pseudo) the loop is jumped out and the loop body is no longer executed.

while (i < n)
i = i + 2;

In the above example, i keeps increasing by 2 as long as i is less than n.

If the loop body has more than one statement, you will need to use curly brackets to group these statements together.

while (expression) {
statement;
statement;
}

Here is an example.

i = 0;

while (i < 10) {
printf("i is now %d!\n", i);
i++;
}

printf("All done!\n");

In the above code, the loop will execute 10 times, increasing i by 1 each time until it equals 10 before exiting the loop.

As long as the condition is true, while will produce an infinite loop. Here is a common way of writing an infinite loop.

while (1) {
// ...
}

The above example is an infinite loop, but the loop can be jumped out of inside the body with a break statement.

do... .while structure

The do... while' structure is a variation of while` which executes the loop body once and then determines if the condition is met. If it does, it continues to execute the loop body, otherwise the loop is jumped.

do statement
while (expression);

In the above code, the loop body statement is executed at least once, whether or not the condition expression holds. Each time statement finishes executing, it determines expression once and decides whether to end the loop.

i = 10;

do --i;
while (i > 0);

In the above example, the variable i is first subtracted by 1 and then determined if it is greater than 0. If it is greater than 0, it continues to be subtracted by 1 until i equals 0.

If there are multiple statements in the loop section, they need to be placed inside curly brackets.

i = 10;

do {
printf("i is %d\n", i);
i++;
} while (i < 10);

printf("All done!\n");

In the above example, the variable i does not satisfy the condition of being less than 10, but the loop body is still executed once.

for statement

The for statement is the most commonly used loop construct and is usually used to control the number of loops precisely.

for (initialization; continuation; action)
statement;

In the code above, the conditional part of the for statement (i.e. the part inside the parentheses) has three expressions.

  • initialization: the initialization expression, which is used to initialize the loop variables and is executed only once.
  • continuation: a judgement expression that will keep executing the loop body as long as it is true.
  • action: loop variable handling expression, executed at the end of each round of the loop, causing the loop variable to change.

The statement in the body part of the loop can be a single statement or a compound statement inside curly brackets. Here is an example.

for (int i = 10; i > 0; i--)
printf("i is %d\n", i);

In the example above, the loop variable i is declared inside the first expression of for, which is used only for this loop. It expires after leaving the loop body.

Each of the three expressions in the conditional section can have more than one statement, with statements separated from each other by commas.

int i, j;
for (i = 0, j = 999; i < 10; i++, j--) {
printf("%d, %d\n", i, j);
}

In the example above, the initialisation section has two statements that assign values to the variables i and j respectively.

None of the three expressions in for are required, or even all of them could be omitted, which would form an infinite loop.

for (;;;) {
printf("This line will be printed in an infinite loop. \n" );
}

The above example creates an infinite loop because there is no judgement condition.

The break statement

There are two uses of the break statement. One is used in conjunction with the switch statement to break the execution of a branch, which has already been described. The other use is to jump out of the loop inside the body of the loop and not proceed with the rest of the loop.

for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
printf("%d, %d\n", i, j);
break;
}
}

In the above example, the break statement makes the loop jump to the next i.

while ((ch = getchar()) ! = EOF) {
if (ch == '\n') break;
putchar(ch);
}

In the above example, once the newline character (\n) is read, the break command jumps out of the entire while loop and does not continue reading.

Note that the break command can only jump out of the loop body and the switch` structure, not the if` structure.

if (n > 1) {
if (n > 2) break; // invalid
printf("hello\n");
}

In the above example, the break statement is invalid because it does not jump out of the outer if structure.

continue statement

The continue statement is used to terminate the current loop inside the loop body and move on to the next loop. Whenever a continue statement is encountered, the subsequent statements inside the loop body are not executed, and the loop returns to the head of the loop body to start the next round of execution.

for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
printf("%d, %d\n", i, j);
continue;
}
}

The above example, with or without the continue statement, has the same effect, both indicate a jump to the next j.

while ((ch = getchar()) ! = '\n') {
if (ch == '\t') continue;
putchar(ch);
}

In the above example, whenever the character read is a tab (\t), the continue statement is used to skip that character and read the next one.

goto statement

The goto statement is used to jump to the specified tab name. This can break structured programming and is not recommended to be used lightly. Its usage is described here for syntactic completeness.

char ch;

top: ch = getchar();

if (ch == 'q')
goto top;

In the above example, top is a tag name that can be placed before the normal statement, which is equivalent to marking the line. The program executes to the goto statement and jumps to the tag name it specifies.

infinite_loop:
print("Hello, world!\n");
goto infinite_loop;

The above code will produce an infinite loop.

One of the main uses of goto is to jump out of a multi-layered loop.

for(...) {
for (...) {
while (...) {
do {
if (some_error_condition)
goto bail;
} while(...) ;
}
}
}

bail:
// ... ...

The above code has a very complex nested loop, and it would be a pain to write without goto to jump out of all the loops completely.

Another use for goto is to end multiple judgements early.

if (do_something() == ERR)
goto error;
if (do_something2() == ERR)
goto error;
if (do_something3() == ERR)
goto error;
if (do_something4() == ERR)
goto error;

The above example has four judgements, and as soon as one of them finds an error, you use goto to skip the subsequent ones.

Note that goto can only jump within the same function, and not to other functions.